Import data

Four dataframes are imported:

  • data_ori: It contains the original data with labels.
  • data_ss: It contains the semi-supervised data, which includes both labeled and unlabeled data.
  • data_label: It contains the labeled data of the unlabeled data.
  • data_test: It contains the test data.

Simulation explanation

The data was simulated using the function make_blobs from the sklearn.datasets library in Python. The function generates Gaussian blobs for clustering. The data was generated with the following parameters:

  • Number of samples: 17000
  • Number of classes: 5 because there five types of myositis
  • Number of features: 5
  • Number of test samples: 3400 (20% of the total samples)
  • Number of semi-supervised samples: 13600 (80% of the total samples)
  • Label rate for semi-supervised learning: 0.01 (1% of the data is labeled)
  • Number of labeled samples: 136 (1% of the semi-supervised data)
  • Standard deviation of the clusters: 2
  • Number of centers (classes) for the blobs: 5

Data exploration

Table 1: Dimensions of the data frames
Data Rows Columns labeled unlabeled
Original Data 17000 5 17000 0
Semi Supervised Data 13600 5 136 13464
Labeled Data 13464 5 13464 0
Test Data 3400 5 3400 0

Descritive Statistics

The boxplots below show the distribution of the features in the original data, semi-supervised data, labeled data, and test data. The boxplots will help us to visualize the distribution of the features and to identify any outliers in the data.

Each Variable

Feature 0

df %>% 
  filter(source != "Unlabeled Data") %>%
  ggplot(aes(x = source, y = X0)) +
  geom_boxplot() +
  geom_jitter(aes(color = source), alpha = 0.5, width = 0.1) +
  labs(title = "Distribution of Feature 0", x = "Source", y = "Feature 0") +
  theme_bw() +
  facet_wrap(~target, scales = "free") +
  theme(legend.position = "bottom",
        plot.title = element_text(size = 14,hjust = 0.5),
        legend.title = element_blank(),
        axis.text.x =  element_blank())

Feature 1

df %>% 
  filter(source != "Unlabeled Data") %>%
  ggplot(aes(x = source, y = X1)) +
  geom_boxplot() +
  geom_jitter(aes(color = source), alpha = 0.5, width = 0.1) +
  labs(title = "Distribution of Feature 1", x = "Source", y = "Feature 1") +
  theme_bw() +
  facet_wrap(~target, scales = "free") +
  theme(legend.position = "bottom",
        plot.title = element_text(size = 14,hjust = 0.5),
        legend.title = element_blank(),
        axis.text.x =  element_blank())

Feature 2

df %>% 
  filter(source != "Unlabeled Data") %>%
  ggplot(aes(x = source, y = X2)) +
  geom_boxplot() +
  geom_jitter(aes(color = source), alpha = 0.5, width = 0.1) +
  labs(title = "Distribution of Feature 2", x = "Source", y = "Feature 2") +
  theme_bw() +
  facet_wrap(~target, scales = "free") +
  theme(legend.position = "bottom",
        plot.title = element_text(size = 14,hjust = 0.5),
        legend.title = element_blank(),
        axis.text.x =  element_blank())

Feature 3

df %>% 
  filter(source != "Unlabeled Data") %>%
  ggplot(aes(x = source, y = X3)) +
  geom_boxplot() +
  geom_jitter(aes(color = source), alpha = 0.5, width = 0.1) +
  labs(title = "Distribution of Feature 3", x = "Source", y = "Feature 3") +
  theme_bw() +
  facet_wrap(~target, scales = "free") +
  theme(legend.position = "bottom",
        plot.title = element_text(size = 14,hjust = 0.5),
        legend.title = element_blank(),
        axis.text.x =  element_blank())

Feature 4

df %>% 
  filter(source != "Unlabeled Data") %>%
  ggplot(aes(x = source, y = X4)) +
  geom_boxplot() +
  geom_jitter(aes(color = source), alpha = 0.5, width = 0.1) +
  labs(title = "Distribution of Feature 4", x = "Source", y = "Feature 4") +
  theme_bw() +
  facet_wrap(~target, scales = "free") +
  theme(legend.position = "bottom",
        plot.title = element_text(size = 14,hjust = 0.5),
        legend.title = element_blank(),
        axis.text.x =  element_blank())

Label distribution

The label distribution shows the number of samples for each class in the original data, semi-supervised data, and test data. The distribution will help us to understand the balance of the classes in the data.

Pairs plots

In this section, we will visualize the data using pairs plots. The pairs plots will show the relationships between the features in the data. The original data will be compared with the semi-supervised data, which includes both labeled and unlabeled data.

Original data

Semi-supervised data Labeled

# Semi Supervised data
#my_colors <- c("blue", "green", "purple", "orange","brown")

# Labeled data
data_ss %>% 
      filter(target != '-1') %>% 
        ggpairs(columns = 1:5,
                aes(color = target, alpha = 0.5)) 

  #scale_fill_manual(values = my_colors) +
  #scale_color_manual(values = my_colors)

Semi-supervised data Unlabeled

# Unlabeled data
data_ss %>% 
      filter(target == '-1') %>% 
        ggpairs(columns = 1:5, aes(alpha = 0.5)) +
  scale_fill_manual(values = 'black') +
  scale_color_manual(values = 'black')

Test data

# Test data
data_test %>% 
        ggpairs(columns = 1:5,
                aes(color = target,  
                alpha = 0.5))

LS0tCnRpdGxlOiAiRGF0YSBzaW11bGF0aW9uIgphdXRob3I6ICJqZmphIgpvdXRwdXQ6CiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOiAKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogbm8KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKLS0tCgoKYGBge3IgbGlicmFyaWVzLGVjaG89IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIGluY2x1ZGUgeW91ciBsaWJyYXJpZXMgaGVyZQojIHVzZSBlY2hvID0gRkFMU0UgaWYgeW91IGRvIG5vdCB3YW50IHRoZSBDb2RlIGJ1dHRvbiB0byBhcHBlYXIKcm0obGlzdCA9IGxzKCkpCmxpYnJhcnkodGlkeXZlcnNlKQojIExpYnJhcnkgZm9yIHBsb3R0aW5nCmxpYnJhcnkoZ2dwbG90MikgCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGdncmlkZ2VzKQpsaWJyYXJ5KEdHYWxseSkKbGlicmFyeShrYWJsZUV4dHJhKSAjIGZvciBuaWNlciB0YWJsZXMKCmBgYAoKIyBJbXBvcnQgZGF0YQoKRm91ciBkYXRhZnJhbWVzIGFyZSBpbXBvcnRlZDoKCi0gYGRhdGFfb3JpYDogSXQgY29udGFpbnMgdGhlIG9yaWdpbmFsIGRhdGEgd2l0aCBsYWJlbHMuCi0gYGRhdGFfc3NgOiBJdCBjb250YWlucyB0aGUgc2VtaS1zdXBlcnZpc2VkIGRhdGEsIHdoaWNoIGluY2x1ZGVzIGJvdGggbGFiZWxlZCBhbmQgdW5sYWJlbGVkIGRhdGEuCi0gYGRhdGFfbGFiZWxgOiBJdCBjb250YWlucyB0aGUgbGFiZWxlZCBkYXRhIG9mIHRoZSB1bmxhYmVsZWQgZGF0YS4KLSBgZGF0YV90ZXN0YDogSXQgY29udGFpbnMgdGhlIHRlc3QgZGF0YS4KCmBgYHtyLGVjaG89RkFMU0V9CiMgT3JpZ2luYWwgZGF0YQpkYXRhX29yaSA9IHJlYWQuY3N2KCIuLi9kYXRhL2RmX29yaS5jc3YiKQpkYXRhX29yaSA9IGRhdGFfb3JpICU+JSAKICAgICAgICAgICAgbXV0YXRlKHRhcmdldCA9IGFzLmZhY3Rvcih0YXJnZXQpKSAjIENvbnZlcnQgdGFyZ2V0IHRvIGZhY3RvciBmb3IgY2xhc3NpZmljYXRpb24KIyBTZW1pIFN1cGVydmlzZWQgZGF0YQpkYXRhX3NzID0gcmVhZC5jc3YoIi4uL2RhdGEvZGZfWC5jc3YiKQpkYXRhX3NzID0gZGF0YV9zcyAlPiUgCiAgICAgICAgICAgIG11dGF0ZSh0YXJnZXQgPSBhcy5mYWN0b3IodGFyZ2V0KSkgIyBDb252ZXJ0IHRhcmdldCB0byBmYWN0b3IgZm9yIGNsYXNzaWZpY2F0aW9uCiMgVW5sYWJlbCBkYXRhCmRhdGFfbGFiZWwgPSByZWFkLmNzdigiLi4vZGF0YS9kZl91bmxhYmVsLmNzdiIpCmRhdGFfbGFiZWwgPSBkYXRhX2xhYmVsICU+JSAKICAgICAgICAgICAgbXV0YXRlKHRhcmdldCA9IGFzLmZhY3Rvcih0YXJnZXQpKSAjIENvbnZlcnQgdGFyZ2V0IHRvIGZhY3RvciBmb3IgY2xhc3NpZmljYXRpb24KIyBUZXN0IGRhdGEKZGF0YV90ZXN0ID0gcmVhZC5jc3YoIi4uL2RhdGEvZGZfdGVzdC5jc3YiKQpkYXRhX3Rlc3QgPSBkYXRhX3Rlc3QgJT4lIAogICAgICAgICAgICBtdXRhdGUodGFyZ2V0ID0gYXMuZmFjdG9yKHRhcmdldCkpICMgQ29udmVydCB0YXJnZXQgdG8gZmFjdG9yIGZvciBjbGFzc2lmaWNhdGlvbgpgYGAKCgojIFNpbXVsYXRpb24gZXhwbGFuYXRpb24KVGhlIGRhdGEgd2FzIHNpbXVsYXRlZCB1c2luZyB0aGUgZnVuY3Rpb24gYG1ha2VfYmxvYnNgIGZyb20gdGhlIGBza2xlYXJuLmRhdGFzZXRzYCBsaWJyYXJ5IGluIFB5dGhvbi4gVGhlIGZ1bmN0aW9uIGdlbmVyYXRlcyBHYXVzc2lhbiBibG9icyBmb3IgY2x1c3RlcmluZy4gVGhlIGRhdGEgd2FzIGdlbmVyYXRlZCB3aXRoIHRoZSBmb2xsb3dpbmcgcGFyYW1ldGVyczoKCi0gTnVtYmVyIG9mIHNhbXBsZXM6IDE3MDAwCi0gTnVtYmVyIG9mIGNsYXNzZXM6IDUgYmVjYXVzZSB0aGVyZSBmaXZlIHR5cGVzIG9mIG15b3NpdGlzCi0gTnVtYmVyIG9mIGZlYXR1cmVzOiA1Ci0gTnVtYmVyIG9mIHRlc3Qgc2FtcGxlczogMzQwMCAoMjAlIG9mIHRoZSB0b3RhbCBzYW1wbGVzKQotIE51bWJlciBvZiBzZW1pLXN1cGVydmlzZWQgc2FtcGxlczogMTM2MDAgKDgwJSBvZiB0aGUgdG90YWwgc2FtcGxlcykKLSBMYWJlbCByYXRlIGZvciBzZW1pLXN1cGVydmlzZWQgbGVhcm5pbmc6IDAuMDEgKDElIG9mIHRoZSBkYXRhIGlzIGxhYmVsZWQpCi0gTnVtYmVyIG9mIGxhYmVsZWQgc2FtcGxlczogMTM2ICgxJSBvZiB0aGUgc2VtaS1zdXBlcnZpc2VkIGRhdGEpCi0gU3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBjbHVzdGVyczogMgotIE51bWJlciBvZiBjZW50ZXJzIChjbGFzc2VzKSBmb3IgdGhlIGJsb2JzOiA1CgojIERhdGEgZXhwbG9yYXRpb24KCgoKYGBge3IsIGVjaG89RkFMU0V9CiMgVGFibGUgd2l0aCB0aGUgZGltZW5zaW9ucyBvZiBhbGwgZGF0YSBmcmFtZXMKZGZfZGltZW5zaW9ucyA8LQogICAgICAgICAgICAgICAgZGF0YS5mcmFtZSgKICAgICAgICAgICAgICAgICAgRGF0YSA9IGMoIk9yaWdpbmFsIERhdGEiLCAiU2VtaSBTdXBlcnZpc2VkIERhdGEiLCAiTGFiZWxlZCBEYXRhIiwgIlRlc3QgRGF0YSIpLAogICAgICAgICAgICAgICAgICBSb3dzID0gYyhucm93KGRhdGFfb3JpKSwgbnJvdyhkYXRhX3NzKSwgbnJvdyhkYXRhX2xhYmVsKSwgbnJvdyhkYXRhX3Rlc3QpKSwKICAgICAgICAgICAgICAgICAgQ29sdW1ucyA9IGMobmNvbChkYXRhX29yaSksIG5jb2woZGF0YV9zcyksIG5jb2woZGF0YV9sYWJlbCksIG5jb2woZGF0YV90ZXN0KSktMSwKICAgICAgICAgICAgICAgICAgbGFiZWxlZCA9IGMoc3VtKGRhdGFfb3JpJHRhcmdldCAhPSAnLTEnKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bShkYXRhX3NzJHRhcmdldCAhPSAnLTEnKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bShkYXRhX2xhYmVsJHRhcmdldCAhPSAnLTEnKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bShkYXRhX3Rlc3QkdGFyZ2V0ICE9ICctMScpKSwKICAgICAgICAgICAgICAgICAgdW5sYWJlbGVkID0gYyhzdW0oZGF0YV9vcmkkdGFyZ2V0ID09ICctMScpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtKGRhdGFfc3MkdGFyZ2V0ID09ICctMScpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtKGRhdGFfbGFiZWwkdGFyZ2V0ID09ICctMScpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtKGRhdGFfdGVzdCR0YXJnZXQgPT0gJy0xJykpCiAgICAgICAgICAgICAgICApCgpkZl9kaW1lbnNpb25zICU+JQogIGthYmxlKCJodG1sIiwgY2FwdGlvbiA9ICJEaW1lbnNpb25zIG9mIHRoZSBkYXRhIGZyYW1lcyIpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gRikgJT4lCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUpICU+JQogIGNvbHVtbl9zcGVjKDI6NSwgd2lkdGggPSAiM2NtIikgJT4lCiAgcm93X3NwZWMoMCwgYm9sZCA9IFRSVUUsIGJhY2tncm91bmQgPSAiI0Q5RURGNyIpICU+JQogIHJvd19zcGVjKDE6bnJvdyhkZl9kaW1lbnNpb25zKSwgYmFja2dyb3VuZCA9ICIjRjVGNUY1IikKCmBgYAoKIyMgRGVzY3JpdGl2ZSBTdGF0aXN0aWNzCgogCgpgYGB7ciwgZWNobz1GQUxTRX0KIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciB0aGUgb3JpZ2luYWwgZGF0YQpkc19vcmkgPSBkYXRhX29yaSAlPiUgCiAgICAgICAgICBzZWxlY3QoLXRhcmdldCkgJT4lIAogICAgICAgICAgc3VtbWFyaXNlKGFjcm9zcyhldmVyeXRoaW5nKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QobWVhbiA9IG1lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2QgPSBzZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4gPSBtaW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcTI1ID0gfnF1YW50aWxlKC4sIDAuMjUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbiA9IG1lZGlhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxNzUgPSB+cXVhbnRpbGUoLiwgMC43NSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4ID0gbWF4ICkpKSAlPiUKICAgICAgICAgIG11dGF0ZShzb3VyY2UgPSAiT3JpZ2luYWwgRGF0YSIpIAogICAgICAgICAgCiMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcyBmb3IgdGhlIHNlbWktc3VwZXJ2aXNlZCBkYXRhCmRzX3NzID0gZGF0YV9zcyAlPiUgCiAgICAgICAgICBzZWxlY3QoLXRhcmdldCkgJT4lIAogICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShhY3Jvc3MoZXZlcnl0aGluZygpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4gPSBtZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkID0gc2QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluID0gbWluLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHEyNSA9IH5xdWFudGlsZSguLCAwLjI1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYW4gPSBtZWRpYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcTc1ID0gfnF1YW50aWxlKC4sIDAuNzUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heCA9IG1heCApKSkgJT4lCiAgICAgICAgICBtdXRhdGUoc291cmNlID0gIlNlbWkgU3VwZXJ2aXNlZCBEYXRhIikKIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciB0aGUgbGFiZWxlZCBkYXRhIGluIHRoZSBzcyBkYXRhCmRzX2xhYmVsID0gZGF0YV9zcyAlPiUgCiAgICAgICAgICBmaWx0ZXIodGFyZ2V0ICE9ICctMScpICU+JQogICAgICAgICAgc2VsZWN0KC10YXJnZXQpICU+JSAKICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2UoYWNyb3NzKGV2ZXJ5dGhpbmcoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuID0gbWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZCA9IHNkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbiA9IG1pbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxMjUgPSB+cXVhbnRpbGUoLiwgMC4yNSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFuID0gbWVkaWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHE3NSA9IH5xdWFudGlsZSguLCAwLjc1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXggPSBtYXggKSkpICU+JQogICAgICAgICAgbXV0YXRlKHNvdXJjZSA9ICJMYWJlbGVkIERhdGEiKQoKIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciB0aGUgdGVzdCBkYXRhCmRzX3Rlc3QgPSBkYXRhX3Rlc3QgJT4lIAogICAgICAgICAgc2VsZWN0KC10YXJnZXQpICU+JSAKICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShhY3Jvc3MoZXZlcnl0aGluZygpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0KG1lYW4gPSBtZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkID0gc2QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluID0gbWluLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHEyNSA9IH5xdWFudGlsZSguLCAwLjI1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYW4gPSBtZWRpYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcTc1ID0gfnF1YW50aWxlKC4sIDAuNzUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heCA9IG1heCApKSkgJT4lCiAgICAgICAgICAgIG11dGF0ZShzb3VyY2UgPSAiVGVzdCBEYXRhIikKCiMgVW5pb24gb2YgdGhlIHRhYmxlcwpkcyA9IGJpbmRfcm93cyhkc19vcmksIGRzX3NzLCBkc19sYWJlbCwgZHNfdGVzdCkKZHMgPSBkcyAlPiUgCiAgICAgIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwyKSkpCmBgYAoKClRoZSBib3hwbG90cyBiZWxvdyBzaG93IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIGZlYXR1cmVzIGluIHRoZSBvcmlnaW5hbCBkYXRhLCBzZW1pLXN1cGVydmlzZWQgZGF0YSwgbGFiZWxlZCBkYXRhLCBhbmQgdGVzdCBkYXRhLiBUaGUgYm94cGxvdHMgd2lsbCBoZWxwIHVzIHRvIHZpc3VhbGl6ZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBmZWF0dXJlcyBhbmQgdG8gaWRlbnRpZnkgYW55IG91dGxpZXJzIGluIHRoZSBkYXRhLgoKCmBgYHtyLCBlY2hvPUZBTFNFfQojIENvbmNhdGVuYXRlIGFsbCB0aGUgZGF0YSBmcmFtZXMgZm9yIHBsb3R0aW5nCmRmID0gZGF0YV9vcmkgJT4lIAogIG11dGF0ZShzb3VyY2UgPSAiT3JpZ2luYWwgRGF0YSIpICU+JSAKICBiaW5kX3Jvd3MoZGF0YV9zcyAlPiUgCiAgICAgICAgICAgIGZpbHRlcih0YXJnZXQgPT0gJy0xJykgJT4lCiAgICAgICAgICAgIG11dGF0ZShzb3VyY2UgPSAiVW5sYWJlbGVkIERhdGEiKSkgJT4lIAogIGJpbmRfcm93cyhkYXRhX3NzICU+JSAKICAgICAgICAgICAgZmlsdGVyKHRhcmdldCAhPSAnLTEnKSAlPiUKICAgICAgICAgICAgbXV0YXRlKHNvdXJjZSA9ICJMYWJlbGVkIERhdGEiKSkgJT4lIAogIGJpbmRfcm93cyhkYXRhX3Rlc3QgJT4lIAogICAgICAgICAgICBtdXRhdGUoc291cmNlID0gIlRlc3QgRGF0YSIpKQoKZGYkc291cmNlID0gZmFjdG9yKGRmJHNvdXJjZSwgCiAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJPcmlnaW5hbCBEYXRhIiwgIlVubGFiZWxlZCBEYXRhIiwgIkxhYmVsZWQgRGF0YSIsICJUZXN0IERhdGEiKSkKCmBgYAoKIyMjIEVhY2ggVmFyaWFibGUgey50YWJzZXR9CgojIyMjIEZlYXR1cmUgMCAKCmBgYHtyfQpkZiAlPiUgCiAgZmlsdGVyKHNvdXJjZSAhPSAiVW5sYWJlbGVkIERhdGEiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzb3VyY2UsIHkgPSBYMCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gc291cmNlKSwgYWxwaGEgPSAwLjUsIHdpZHRoID0gMC4xKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgRmVhdHVyZSAwIiwgeCA9ICJTb3VyY2UiLCB5ID0gIkZlYXR1cmUgMCIpICsKICB0aGVtZV9idygpICsKICBmYWNldF93cmFwKH50YXJnZXQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LGhqdXN0ID0gMC41KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSAgZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyMgRmVhdHVyZSAxCmBgYHtyfQpkZiAlPiUgCiAgZmlsdGVyKHNvdXJjZSAhPSAiVW5sYWJlbGVkIERhdGEiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzb3VyY2UsIHkgPSBYMSkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gc291cmNlKSwgYWxwaGEgPSAwLjUsIHdpZHRoID0gMC4xKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgRmVhdHVyZSAxIiwgeCA9ICJTb3VyY2UiLCB5ID0gIkZlYXR1cmUgMSIpICsKICB0aGVtZV9idygpICsKICBmYWNldF93cmFwKH50YXJnZXQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LGhqdXN0ID0gMC41KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSAgZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyMgRmVhdHVyZSAyCmBgYHtyfQpkZiAlPiUgCiAgZmlsdGVyKHNvdXJjZSAhPSAiVW5sYWJlbGVkIERhdGEiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzb3VyY2UsIHkgPSBYMikpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gc291cmNlKSwgYWxwaGEgPSAwLjUsIHdpZHRoID0gMC4xKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgRmVhdHVyZSAyIiwgeCA9ICJTb3VyY2UiLCB5ID0gIkZlYXR1cmUgMiIpICsKICB0aGVtZV9idygpICsKICBmYWNldF93cmFwKH50YXJnZXQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LGhqdXN0ID0gMC41KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSAgZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyMgRmVhdHVyZSAzCgpgYGB7cn0KZGYgJT4lIAogIGZpbHRlcihzb3VyY2UgIT0gIlVubGFiZWxlZCBEYXRhIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc291cmNlLCB5ID0gWDMpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGdlb21faml0dGVyKGFlcyhjb2xvciA9IHNvdXJjZSksIGFscGhhID0gMC41LCB3aWR0aCA9IDAuMSkgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEZlYXR1cmUgMyIsIHggPSAiU291cmNlIiwgeSA9ICJGZWF0dXJlIDMiKSArCiAgdGhlbWVfYncoKSArCiAgZmFjZXRfd3JhcCh+dGFyZ2V0LCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCxoanVzdCA9IDAuNSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ID0gIGVsZW1lbnRfYmxhbmsoKSkKYGBgCgojIyMjIEZlYXR1cmUgNApgYGB7cn0KZGYgJT4lIAogIGZpbHRlcihzb3VyY2UgIT0gIlVubGFiZWxlZCBEYXRhIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc291cmNlLCB5ID0gWDQpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGdlb21faml0dGVyKGFlcyhjb2xvciA9IHNvdXJjZSksIGFscGhhID0gMC41LCB3aWR0aCA9IDAuMSkgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEZlYXR1cmUgNCIsIHggPSAiU291cmNlIiwgeSA9ICJGZWF0dXJlIDQiKSArCiAgdGhlbWVfYncoKSArCiAgZmFjZXRfd3JhcCh+dGFyZ2V0LCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCxoanVzdCA9IDAuNSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ID0gIGVsZW1lbnRfYmxhbmsoKSkKYGBgCgojIyBMYWJlbCBkaXN0cmlidXRpb24KVGhlIGxhYmVsIGRpc3RyaWJ1dGlvbiBzaG93cyB0aGUgbnVtYmVyIG9mIHNhbXBsZXMgZm9yIGVhY2ggY2xhc3MgaW4gdGhlIG9yaWdpbmFsIGRhdGEsIHNlbWktc3VwZXJ2aXNlZCBkYXRhLCBhbmQgdGVzdCBkYXRhLiBUaGUgZGlzdHJpYnV0aW9uIHdpbGwgaGVscCB1cyB0byB1bmRlcnN0YW5kIHRoZSBiYWxhbmNlIG9mIHRoZSBjbGFzc2VzIGluIHRoZSBkYXRhLgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0gCiMgTGFiZWwgZGlzdHJpYnV0aW9uIGZvciB0aGUgb3JpZ2luYWwgZGF0YQpkZiAlPiUgCiAgZmlsdGVyKHRhcmdldCAhPSAnLTEnKSAlPiUKICBncm91cF9ieShzb3VyY2UsIHRhcmdldCkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkoc291cmNlKSAlPiUKICBtdXRhdGUodG90YWwgPSBzdW0oY291bnQpKSAlPiUKICBtdXRhdGUocHJvcCA9IGNvdW50IC8gdG90YWwgKiAxMDApICU+JQogIGdncGxvdChhZXMoeCA9IHRhcmdldCwgeSA9IHByb3AsIGZpbGwgPSB0YXJnZXQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChzY2FsZSA9IDEpKSArCiAgbGFicyh0aXRsZSA9ICJMYWJlbCBEaXN0cmlidXRpb24gaW4gT3JpZ2luYWwgRGF0YSIsIHggPSAiRmVhdHVyZSIsIHkgPSAiQ291bnQiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LGhqdXN0ID0gMC41KSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSsKICBmYWNldF93cmFwKH5zb3VyY2UsIHNjYWxlcyA9ICJmcmVlIikgCgpgYGAKCiMjIFBhaXJzIHBsb3RzIHsudGFic2V0fQoKSW4gdGhpcyBzZWN0aW9uLCB3ZSB3aWxsIHZpc3VhbGl6ZSB0aGUgZGF0YSB1c2luZyBwYWlycyBwbG90cy4gVGhlIHBhaXJzIHBsb3RzIHdpbGwgc2hvdyB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHRoZSBmZWF0dXJlcyBpbiB0aGUgZGF0YS4gVGhlIG9yaWdpbmFsIGRhdGEgd2lsbCBiZSBjb21wYXJlZCB3aXRoIHRoZSBzZW1pLXN1cGVydmlzZWQgZGF0YSwgd2hpY2ggaW5jbHVkZXMgYm90aCBsYWJlbGVkIGFuZCB1bmxhYmVsZWQgZGF0YS4gCgojIyMgT3JpZ2luYWwgZGF0YQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRX0KIyBPcmlnaW5hbCBkYXRhCmRhdGFfb3JpICU+JSAKICAgICAgICBnZ3BhaXJzKGNvbHVtbnMgPSAxOjUsCiAgICAgICAgICAgICAgICBhZXMoY29sb3IgPSB0YXJnZXQsICAKICAgICAgICAgICAgICAgIGFscGhhID0gMC41KSkKYGBgCgojIyMgU2VtaS1zdXBlcnZpc2VkIGRhdGEgTGFiZWxlZApgYGB7cn0KIyBTZW1pIFN1cGVydmlzZWQgZGF0YQojbXlfY29sb3JzIDwtIGMoImJsdWUiLCAiZ3JlZW4iLCAicHVycGxlIiwgIm9yYW5nZSIsImJyb3duIikKCiMgTGFiZWxlZCBkYXRhCmRhdGFfc3MgJT4lIAogICAgICBmaWx0ZXIodGFyZ2V0ICE9ICctMScpICU+JSAKICAgICAgICBnZ3BhaXJzKGNvbHVtbnMgPSAxOjUsCiAgICAgICAgICAgICAgICBhZXMoY29sb3IgPSB0YXJnZXQsIGFscGhhID0gMC41KSkgCiAgI3NjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG15X2NvbG9ycykgKwogICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlfY29sb3JzKQoKYGBgCgoKIyMjIFNlbWktc3VwZXJ2aXNlZCBkYXRhIFVubGFiZWxlZApgYGB7cn0KIyBVbmxhYmVsZWQgZGF0YQpkYXRhX3NzICU+JSAKICAgICAgZmlsdGVyKHRhcmdldCA9PSAnLTEnKSAlPiUgCiAgICAgICAgZ2dwYWlycyhjb2x1bW5zID0gMTo1LCBhZXMoYWxwaGEgPSAwLjUpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAnYmxhY2snKQpgYGAKCiMjIyBUZXN0IGRhdGEKYGBge3J9CiMgVGVzdCBkYXRhCmRhdGFfdGVzdCAlPiUgCiAgICAgICAgZ2dwYWlycyhjb2x1bW5zID0gMTo1LAogICAgICAgICAgICAgICAgYWVzKGNvbG9yID0gdGFyZ2V0LCAgCiAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNSkpCmBgYAoKCgoK